<template>
  <!-- 进度条 -->
  <div v-if="isProgress" class="progress">
    <p :style="'width:' + percentage + '%'"></p>
  </div>
  <!-- <LoginBox :userInfo="memberInfo" :isShowCenter="true"/> -->
  <!-- 页眉 -->
  <div v-if="pageData.pageHeaderOption" class="page_header">
    <div v-if="pageData.pageHeaderOption.type === 'text'" :style="style">
      {{ pageData.pageHeaderOption.textContent }}
    </div>
    <template v-else>
      <Swipe :autoplay="3000" class="my-swipe" indicator-color="white">
        <SwipeItem v-for="img in pageData.pageHeaderOption.images" :key="img">
          <img :src="img.url" alt="" />
        </SwipeItem>
      </Swipe>
    </template>
  </div>
  <!-- 标题和简介 -->
  <div class="survey_top m15">
    <h2 class="f20 t-center" @click="showVConsole">
      {{ pageData.surveyName }}
    </h2>
  </div>
  <!-- 问题区域 -->
  <div
    v-for="(surveyItem, index) in surveyList"
    :key="index"
    class="survey_item"
  >
    <!-- 移动端 -->
    <template v-if="isMobile">
      <van-form
        v-show="index === newPage"
        @failed="onFailed"
        @submit="onSubmit"
      >
        <van-cell-group class="v_form_group">
          <template v-for="item in surveyItem" :key="item.surveyItemId">
            <component
              :is="dom[item.itemType]"
              :item="item"
              @change="change($event)"
            ></component>
          </template>
        </van-cell-group>
        <!-- 按钮区域 -->
        <div class="fixed_btn">
          <div class="err_msg">
            <p v-for="text in subErrorMsg" :key="text" class="f12 red">
              {{ text }}
            </p>
          </div>
          <div class="btn_flex">
            <van-button
              v-if="surveyList.length > 1 && newPage !== 0"
              block
              class="mr15"
              plain
              type="primary"
              @click="newPage--"
            >上一页
            </van-button>
            <van-button block native-type="submit" type="primary"
            >{{ index < surveyList.length - 1 ? "下一页" : "提交" }}
            </van-button>
          </div>
        </div>
      </van-form>
    </template>
    <!-- 电脑端 -->
    <template v-else>
      <ElForm
        v-if="index === newPage"
        ref="ruleFormRef"
        :model="surveyList[index]"
        label-position="top"
      >
        <template
          v-for="(item, childIndex) in surveyItem"
          :key="item.surveyItemId"
        >
          <component :is="domPc[item.itemType]" :childIndex="childIndex" :index="index" :item="item" @change="change($event)"></component>
        </template>
        <div class="m15 mb50 t-center">
          <ElButton
            v-if="surveyList.length > 1 && newPage !== 0"
            class="w100 mr15"
            plain
            type="primary"
            @click="newPage--"
          >
            上一页
          </ElButton>
          <ElButton class="w100" type="primary" @click="submitPc(ruleFormRef)">
            {{ index < surveyList.length - 1 ? "下一页" : "提交" }}
          </ElButton>
        </div>
      </ElForm>
    </template>
  </div>
  <!-- 不能填报的提示 -->
  <Popup
    v-model:show="showPopup"
    :close-on-click-overlay="false"
    :overlay-style="{ background: '#fff' }"
    round
  >
    <Empty :description="resMsg" class="empty" image-size="100" />
  </Popup>
  <!-- 提交动画遮罩 -->
  <Overlay :show="showOverlay">
    <div class="submit_loading">
      <Loading vertical>提交中...</Loading>
    </div>
  </Overlay>
  <!-- 底部弹出 -->
  <AuthPopup
    v-model="showBottom"
    desc="将获取你的姓名、手机号、身份证、工会信息、用于问卷"
    @allow="allow()"
    @reject="router.back()"
  />
</template>
<script setup>
import AuthPopup from "@/components/AuthPopup/index.vue";
import COMPONENTS_H5 from "@/components/components-h5/index";
import COMPONENTS_PC from "@/components/components-pc/index";
import { apiCheckToken, getDetail, submitSurvey, updateUvEvery } from "@/server/business/survey.js";
import { uploadFile } from "@/server/common/file.js";
import { commonStore } from "@/stores/common.js";
import { surveyStore } from "@/stores/survey.js";
import { setWeappToken } from "@/utils/auth.js";
import { formatDate, getDeviceInfo, getSource, getUrlQuery, showVConsole, wxPageRedirect } from "@/utils/common.js";
import { handleLogicData, hideQuestionsWithoutOption } from "@/utils/logic.js";
import { ElButton, ElForm, ElMessage } from "element-plus";
import { storeToRefs } from "pinia";
import { closeToast, Empty, Loading, Overlay, Popup, showLoadingToast, Swipe, SwipeItem } from "vant";
import { computed, inject, onMounted, reactive, ref } from "vue";
import { useRouter } from "vue-router";
import LoginBox from "@/components/loginBox/loginBox.vue";

const { isMobile } = storeToRefs(commonStore());
const dom = COMPONENTS_H5; // 移动端的组件
const domPc = COMPONENTS_PC; // pc端的组件
const useQuery = getUrlQuery(); // href获取数据
const router = useRouter();
const pageData = reactive({});
const newPage = ref(0); // 当前页码
const surveyList = ref([]); // 分页答题数据 修改此数据 实现页面联动
const surveyIndex = ref(0); // 处理数据的时候用来存放第几页
const showOverlay = ref(false);
const metaData = []; // 整理好的元数据
const sysData = {}; // 设备系统数据
const subErrorMsg = ref([]); // 提交表单报错信息
const showPopup = ref(false); // 不能填报信息展示
const resMsg = ref(); // 不能填报原因
const ruleFormRef = ref(); // pc端表单
const percentage = ref(0); // 进度条 数值
const isProgress = ref(false); // 进度条 是否展示
const backTop = inject("backTop"); // 返回顶部
const showBottom = ref(false);
let memberInfo = reactive({});
let metaInfo = {}
let hiddenQuestionData = []; // 隐藏问题的数据 只有工会组件有隐藏功能
const style = computed(() => {
  return {
    fontSize: pageData.pageHeaderOption.font.size + "px",
    color: pageData.pageHeaderOption.font.color,
    fontWeight: pageData.pageHeaderOption.font.bold ? "bold" : "400",
    fontStyle: pageData.pageHeaderOption.font.italic ? "italic" : "initial",
    textDecoration: pageData.pageHeaderOption.font.underline
      ? "underline"
      : "initial",
    textAlign: pageData.pageHeaderOption.font.align,
    background: pageData.pageHeaderOption.font.background
  };
});

// 值发生变动
const change = (event) => {
  // 交互逻辑检测
  handleLogicData(metaData, pageData, event); // 逻辑处理
  disposalData(); // 数据从新渲染
  if (isProgress.value) {
    let newList = surveyList.value.flat(2);
    let already = 0;
    let total = newList.length;
    newList.forEach((item) => {
      if (item.value && item.value.length > 0) already++;
    });
    percentage.value = (already / total) * 100;
  }
};
// 提交 / 下一页
const onSubmit = () => {
  backTop();
  subErrorMsg.value = [];
  if (newPage.value === surveyList.value.length - 1) disposalSubmitData(); // 整理提交数据后在提交
  else newPage.value++;
};
// pc 端提交
const submitPc = async (ruleForm) => {
  if (!ruleForm) return;
  ruleForm[0].validate((field) => {
    if (field) onSubmit();
  });
};
// 整理数据
const disposalSubmitData = () => {
  let newList = surveyList.value.flat(2);
  newList = newList.concat(hiddenQuestionData);
  let pall = newList.map((item) => getSurveyItemVal(item));
  showOverlay.value = true;
  Promise.all(pall)
    .then((list) => {
      let pageHeader = {
        pageHeaderOption: pageData.pageHeaderOption,
        surveyName: pageData.surveyName
      };
      surveyStore().setSurveyInfo({
        pageData: { ...pageHeader, ...pageData },
        surveyList: surveyList.value
      }); // 先将数据缓存 需要先上传文件 然后将surveyList里面的文件数据替换成上传后的数据
      let params = {
        answerReqList: list,
        ...sysData,
        endTime: formatDate(new Date(), "yyyy-MM-dd hh:mm:ss"),
        userInfo: memberInfo,
        pageFullData: JSON.stringify({
          pageData: pageHeader,
          surveyList: surveyList.value
        })
      };
      if (useQuery.staffUserId) {
        params.staffUserId = useQuery.staffUserId;
      }
      submitSurvey(params)
        .then(({ msg }) => {
          ElMessage.success(msg || "提交成功");
          router.replace({ name: "SurveySuccess" }); // 跳转到成功页面
        })
        .finally(() => {
          showOverlay.value = false;
        });
    })
    .catch((msg) => {
      console.error(msg);
    });
};
// 同步获取值
const getSurveyItemVal = (item) => {
  return new Promise((resolve) => {
    let findFile = ["file-upload", "picture-upload"]; // 文件需要上传文件后 拿到上传文件成功后返回的地址
    if (findFile.includes(item.itemType)) {
      let fileData = uploadFileFunc(item); // 返回一个promise
      resolve(fileData);
    } else {
      let value = "";
      let ids = "";
      let respondData = JSON.parse(JSON.stringify(item.value || ""));
      if (item.itemType === "radio") {
        let obj2 = item.itemOptResList.filter(
          (i) => i.optionName === respondData
        )[0];
        let obj = obj2 ? obj2 : {};
        value = obj?.optionValue || "";
        ids = obj?.itemOptionId || "";
        if (obj && obj?.isOther === "Y") respondData = obj.otherValue;
      }
      if (item.itemType === "checkbox") {
        value = [];
        ids = [];
        item.itemOptResList.forEach((row) => {
          if (item.value.includes(row?.optionName)) {
            value.push(row?.optionValue);
            ids.push(row?.itemOptionId);
          }
          let i = respondData.indexOf(row?.optionName);
          if (i >= 0 && row?.isOther === "Y") {
            respondData[i] = row.otherValue;
          }
        });
      }
      if (item.itemType === "select" || item.itemType === "tradeunion") {
        let obj = item.itemOptResList.filter(
          (row) => row?.optionName === item.value
        )[0];
        value = obj?.optionValue || "";
        ids = obj?.itemOptionId || "";
      }
      resolve({
        surveyItemId: item.surveyItemId,
        respondData: Array.isArray(respondData)
          ? respondData.join("/")
          : respondData.toString(),
        respondValue: value.toString(),
        respondId: ids.toString(),
        surveyItemType: item.itemType
      });
    }
  });
};
// 文件上传
const uploadFileFunc = (item) => {
  return new Promise((resolve) => {
    let pall = item.value.map((file) => {
      let formDate = new FormData();
      formDate.append("file", file.file || file.raw);
      return uploadFile(formDate);
    });
    Promise.all(pall)
      .then((list) => {
        item.value = list.map((next) => {
          let obj = next.data;
          obj.file = { name: obj.name };
          return obj;
        }); // 偷偷 将value的file对象改成 接口返回的obj
        resolve({
          surveyItemId: item.surveyItemId,
          respondData: JSON.stringify(list.map((next) => next.data))
        });
      })
      .catch((msg) => console.error(msg));
  });
};
// 提交报错信息
const onFailed = (errorInfo) => {
  if (pageData?.isOneItemPage === "Y") return;
  subErrorMsg.value = errorInfo.errors.map((item) => item.message);
  console.log("failed", errorInfo);
};
// 获取问卷详情
const getSurveyDetail = async () => {
  showLoadingToast({
    message: "加载中...",
    forbidClick: true,
    duration: 0
  });
  let params = { get_request: { surveyId: useQuery.id } };
  getDetail(params).then(async ({ data }) => {
    closeToast();
    document.title = data.surveyName || "业务中台";
    if (data && data.collectStatus && Number(data.collectStatus) === 3) {
      showPopup.value = true;
      resMsg.value = "当前问卷已暂停收集";
      return;
    }
    resMsg.value = data?.checkFillingEnable;
    showPopup.value = !!data?.checkFillingEnable;
    if (showPopup.value) return; // 不能填报 直接展示错误信息 不去渲染页面
    Object.assign(pageData, data);
    // 如果有 staffUserId 则为站内信 不进行用户信息获取
    if (!useQuery.staffUserId) {
      metaInfo = JSON.parse(data.metaInfo)
      await needCheckToken(data?.memberRange);
    } // 获取用户信息
    dialogConfirm(data.surveyItemResList, data);
  });
};
// 弹出授权框
const dialogConfirm = (surveyItemResList, data) => {
  let has = (surveyItemResList || []).some((item) =>
    [
      "membername",
      "membermobile",
      "memberidentity",
      "tradeunion",
      "companyname"
    ].includes(item.itemType)
  );
  if (has) {
    showBottom.value = true;
  } else {
    disposalMateData(surveyItemResList);
    isProgress.value = JSON.parse(data.metaInfo)?.formConfig?.showProgress;
  }
};
// 同意
const allow = () => {
  showBottom.value = false;
  disposalMateData(pageData.surveyItemResList);
  isProgress.value = JSON.parse(pageData.metaInfo)?.formConfig?.showProgress;
};
// 小程序数据替换
const resetWeappToMeta = (item) => {
  if (item.itemType === "membername") item.value = memberInfo.name || "";
  if (item.itemType === "membermobile") item.value = memberInfo.contactPhone || "";
  if (item.itemType === "memberidentity") item.value = memberInfo.idNum || "";
  if (item.itemType === "tradeunion") item.value = memberInfo.districtTradeUnionName || "";
  if (item.itemType === "companyname") item.value = memberInfo.companyName || "";
};
// 元数据 处理
const disposalMateData = (surveyItemResList) => {
  let types = ["checkbox", "picture-upload", "file-upload", "rate", "slider"];
  surveyItemResList.forEach((obj) => {
    const item = obj || {};
    const vformJson = JSON.parse(item.vformJson || "{}");
    if (item.itemType === "select") {
      let isMultiple = vformJson.options.isMultiple;
      if (isMultiple && isMobile) item.itemType = "checkbox"; // 下拉选择 开启多选且移动端的时候 直接将类型改成‘多选’
    }
    item.value = types.includes(item.itemType) ? [] : "";
    item.list = [];
    item.itemOptResList = item.itemOptResList.map((itemOpt) => {
      itemOpt.otherValue = null;
      itemOpt.show = ref(true);
      return itemOpt;
    });
    if (item.itemType === "checkbox" || item.itemType === "radio") {
      let lists = [];
      item.itemOptResList.forEach((next) => {
        if (next.isDefault === "Y") lists.push(next.optionName);
      });
      if (lists.length > 0) item.value = item.itemType === "radio" ? lists[0] : lists;
    } // 多选,单选 设置默认值
    item.hiddenQuestion = vformJson.options?.hiddenQuestion || false;
    item.orderNum = vformJson.ordNum; // 序号showOrderNum
    item.orderId = vformJson.id;
    item.show = true;
    resetWeappToMeta(item);
    metaData.push(item);
  });
  handleLogicData(metaData, pageData); // 逻辑处理
  disposalData();
};
// 渲染页面的数据处理
const disposalData = () => {
  surveyIndex.value = 0;
  surveyList.value = [];
  hiddenQuestionData = [];
  metaData.forEach((item) => {
    if (eval(item.show)) {
      pageData.isOneItemPage === "Y"
        ? oneQuestionOnePage(item)
        : defaultData(item);
    }
  });
};
// 一题一页数据处理
const oneQuestionOnePage = (item) => {
  if (item.hiddenQuestion) {
    hiddenQuestionData.push(item);
  } else if (
    item.itemType !== "slicer" &&
    item.itemType !== "divider" &&
    !hideQuestionsWithoutOption(item)
  ) {
    surveyList.value[surveyIndex.value] = [];
    surveyList.value[surveyIndex.value].push(item);
    surveyIndex.value++;
  }
};
// 默认处理（非一题一页）
const defaultData = (item) => {
  if (item.itemType !== "slicer") {
    if (item.hiddenQuestion) {
      hiddenQuestionData.push(item);
    } else if (!hideQuestionsWithoutOption(item)) {
      if (!surveyList.value[surveyIndex.value]) {
        surveyList.value[surveyIndex.value] = [];
      }
      surveyList.value[surveyIndex.value].push(item);
    }
  } else {
    surveyIndex.value++;
  }
};
// 采集系统数据
const getSysData = () => {
  getSource().then((type) => {
    sysData.source = type || "h5";
  });
  const mobileInfo = getDeviceInfo();
  sysData.browseType = mobileInfo.browseType;
  sysData.deviceType = mobileInfo.model;
  sysData.osVersion = mobileInfo.os;
  sysData.startTime = formatDate(new Date(), "yyyy-MM-dd hh:mm:ss");
  sysData.surveyId = useQuery.id;
};
// 跳转微信登录
const goWxLogin = () => {
  wxPageRedirect(
    "../authLoginNew/authLoginNew?url=" +
    encodeURIComponent(location.href + "&token=#token#")
  );
};
// token验证
const checkToken = async (type) => {
  return new Promise((resolve, reject) => {
    if (useQuery.token && !["#token%23", "#token#"].includes(useQuery.token)) {
      setWeappToken(useQuery.token);
      apiCheckToken({ memberUserToken: useQuery.token })
        .then((res) => {
          Object.assign(memberInfo, res.data) ;
          localStorage.userInfo = JSON.stringify(res.data);
          if (pageData?.surveyTo !== "all") {
            // 是否面向所有人
            if (type === "register") resolve(); // 注册用户
            else if (type === "realName") memberInfo.name && memberInfo.idNum ? resolve() : reject("pseudonym");
            // 实名职工
            else if (type === "member") memberInfo.companyName && memberInfo.districtTradeUnionName ? resolve() : reject("joinUnion");
            // 工会会员
            else reject("noType");
          }else{
            resolve();
            return;
          } 
        })
        .catch((msg) => {
          resolve("apiError", msg);
        });
    } else {
      if (pageData?.surveyTo === "all") {
        resolve();
        return;
      }
      // 判断是否小程序访问
      getSource().then((type) => {
        if (type === "weapp") reject("noToken"); // 没有token 小程序跳登录
        else {
          let { VITE_APP_ENV } = import.meta.env;
          // 开发环境 允许访问 // 没有token 网页禁止访问
          VITE_APP_ENV === "development" ? resolve() : reject("forbidden");
        }
      });
    }
  });
};
// 错误时执行方法集合
const errorFun = {
  noToken: () => goWxLogin(),
  forbidden: () => {
    showPopup.value = true;
    resMsg.value = "请通过小程序访问";
  },
  pseudonym: () => {
    showPopup.value = true;
    resMsg.value = "此活动仅限“实名职工”参加，请先进行实名认证";
  },
  joinUnion: () => {
    showPopup.value = true;
    resMsg.value = "此活动仅限“工会会员”参加，请先入会";
  },
  noType: () => {
    showPopup.value = true;
    resMsg.value = "限制人群类型错误";
  }
};
// 校验合集
const checks = {
  // 仅注册用户
  register: () => {
    return checks.isTime(
      new Date(memberInfo.logonTime).getTime(),
      `仅限${metaInfo.surveyConfig.joinDateStart}~${metaInfo.surveyConfig.joinDateEnd}时间注册的用户可以提交问卷`
    );
  },
  //仅实名职工 realName
  realName: () => {
    return checks.isTime(
      new Date(memberInfo.realNameTime).getTime(),
      `仅限${metaInfo.surveyConfig.joinDateStart}~${metaInfo.surveyConfig.joinDateEnd}时间实名的用户可以提交问卷`
    );
  },
  //仅工会会员
  member: () => {
    return checks.isTime(
      new Date(memberInfo.membershipTime).getTime(),
      `仅限${metaInfo.surveyConfig.joinDateStart}~${metaInfo.surveyConfig.joinDateEnd}时间加入工会的会员可以提交问卷`
    )
  },
  // 时间限制条件
  isTime: (time, errMsg) => {
    let startTime = new Date(metaInfo.surveyConfig.joinDateStart).getTime();
    let endTime = new Date(metaInfo.surveyConfig.joinDateEnd).getTime();
    if (time < startTime || time > endTime) {
      return errMsg
    }else{
      return 
    }
  },
  // 错误提示
  errorMsg: (msg) => {
    showPopup.value = true;
    resMsg.value = msg
  }
}
// 需要token验证的情况
const needCheckToken = (type) => {
  return new Promise((resolve, reject) => {
    checkToken(type)
      .then(() => {
        if(metaInfo.surveyConfig.isJoinTime === 'Y'){
          let msg = checks[type]()
          msg ? checks.errorMsg(msg) : resolve();
        }else{
          resolve();
        }
      })
      .catch((msg) => {
        errorFun[msg](msg);
        reject();
      });
  });
};
// 挂载后运行
onMounted(() => {
  getSurveyDetail();
  getSysData(); // 获取系统
  updateUvEvery({ surveyId: useQuery.id }); // 更新访问量
});
</script>
<style lang="less" scoped>
.page_header {
  margin-top: 3px;
}

.submit_loading {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
}

.survey_item :deep(.van-field__control--custom) {
  display: block;
}

.my-swipe :deep(.van-swipe-item) {
  color: #fff;
  height: 16rem;
  text-align: center;
  background-color: #39a9ed;

  img {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
}

.fixed_btn {
  position: fixed;
  bottom: -1px;
  width: 34.5rem;
  padding: 1.5rem;
  background: #fff;
  border: none;
  box-shadow: 0 0 1rem var(--van-gray-3);

  .err_msg {
    max-height: 6rem;
    overflow-x: hidden;
    overflow-y: auto;
  }
}

.btn_flex {
  display: flex;
}

.v_form_group {
  padding-bottom: 14rem;
}

.progress {
  position: fixed;
  top: 0;
  width: 100%;
  left: 0;
  z-index: 9999;
  height: 3px;
  margin: 0;
  padding: 0;
  background: #fff;
}

.progress p {
  position: absolute;
  left: 0;
  top: 0;
  margin: 0;
  padding: 0;
  background: var(--el-color-primary);
  height: 3px;
}

.w100 {
  width: 180px;
  padding: 20px;
}

.empty {
  --van-empty-description-padding: 0 40px;
}
</style>
